package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huiminpay.common.cache.Cache;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.transaction.api.dto.PayChannelDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PlatformChannelDTO;
import com.huiminpay.transaction.common.util.RedisUtil;
import com.huiminpay.transaction.convert.PayChannelParamConvert;
import com.huiminpay.transaction.convert.PlatformChannelConvert;
import com.huiminpay.transaction.entity.AppPlatformChannel;
import com.huiminpay.transaction.entity.PayChannelParam;
import com.huiminpay.transaction.entity.PlatformChannel;
import com.huiminpay.transaction.mapper.AppPlatformChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelParamMapper;
import com.huiminpay.transaction.mapper.PlatformChannelMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author amx
 * @date 2020/12/6 22:26
 */
@Service
@Component
@Slf4j
public class PlatformChannelServiceImpl implements PlatformChannelServiceApi {

	@Autowired
	private PlatformChannelMapper platformChannelMapper;

	@Autowired
	private AppPlatformChannelMapper appPlatformChannelMapper;


	@Autowired
	private PayChannelMapper payChannelMapper;

	@Autowired
	private PayChannelParamMapper payChannelParamMapper;

	@Autowired
	private Cache cache;


	/**
	 * 获取服务类型列表信息
	 *
	 * @return 服务类型列表
	 */
	@Override
	public List<PlatformChannelDTO> getAllPlatformChannel() {
		List<PlatformChannel> platformChannels = platformChannelMapper.selectList(null);
		return PlatformChannelConvert.INSTANCE.listentity2listdto(platformChannels);
	}

	/**
	 * 查看应用是否绑定该服务类型
	 *
	 * @param appId appId
	 * @param platformChannelCode platformChannelCode
	 * @return
	 */
	@Override
	public Integer existBindPlatformForApp(String appId, String platformChannelCode) {
		AppPlatformChannel apcCode = findAppPlatformChannelByAppIdAndCode(appId, platformChannelCode);
		if (apcCode == null) {
			return 0;
		}
		return 1;
	}

	/**
	 * 根据惠民支付服务类型code查询第三方支付渠道列表信息
	 *
	 * @param platformChannelCode platformChannelCode
	 * @return PayChannelDTOList
	 */
	@Override
	public List<PayChannelDTO> queryPayChannelByPlatformChannel(String platformChannelCode) {

		return payChannelMapper.findPayChannelByPlatformChannel(platformChannelCode);
	}

	/**
	 * 为应用绑定服务类型
	 *
	 * @param appId               appId
	 * @param platformChannelCode platformChannelCode
	 */
	@Override
	public void bindPlatformForApp(String appId, String platformChannelCode) {

		// TODO: 2020/12/6  校验代码 
		// 根据应用id和platformChannelCode查询platformChannel判断是否已经进行绑定
		AppPlatformChannel apfChannel = findAppPlatformChannelByAppIdAndCode(appId, platformChannelCode);

		if (apfChannel != null) {   // 已经进行绑定

			throw new BusinessException(CommonErrorCode.E_200237);
		} else {   // 未进行绑定
			AppPlatformChannel appPlatformChannel = new AppPlatformChannel();
			appPlatformChannel.setPlatformChannel(platformChannelCode);
			appPlatformChannel.setAppId(appId);

			appPlatformChannelMapper.insert(appPlatformChannel);
		}

	}

	/**
	 * 保存第三方支付渠道参数信息
	 * <p>
	 * 加入redis缓存
	 *
	 * @param payChannelParamDTO
	 * @return
	 */
	@Override
	public PayChannelParamDTO savePayChannelParam(PayChannelParamDTO payChannelParamDTO) {
		// TODO: 2020/12/7  异常处理.................

		//根据应用id和平台服务类型code获取应用绑定服务类型的id
		AppPlatformChannel appPlatformChannel =
				appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
						                                   .eq(AppPlatformChannel::getAppId,
						                                       payChannelParamDTO.getAppId())
						                                   .eq(AppPlatformChannel::getPlatformChannel,
						                                       payChannelParamDTO.getPlatformChannelCode()));

		Long appId = appPlatformChannel.getId();
		// TODO: 2020/12/7  异常处理.................

		//根据第三方支付渠道code和appId查询PayChannelParam
		PayChannelParam payChannelParamDb =
				payChannelParamMapper.selectOne(new LambdaQueryWrapper<PayChannelParam>()
						                                .eq(PayChannelParam::getPayChannel,
						                                    payChannelParamDTO.getPayChannel())
						                                .eq(PayChannelParam::getAppPlatformChannelId,
						                                    appId));

		PayChannelParam payChannelParam = PayChannelParamConvert.INSTANCE.dto2entity(payChannelParamDTO);

		payChannelParam.setAppPlatformChannelId(payChannelParamDb.getId());

		// 判断是新增还是更新
		if (payChannelParamDb.getId() != null) {
			//更新参数配置
			payChannelParam.setId(payChannelParamDb.getId());
			payChannelParamMapper.updateById(payChannelParam);
		} else {
			//新增配置信息
			payChannelParamMapper.insert(payChannelParam);
		}
		payChannelParamDTO.setId(payChannelParam.getId());

		// 把支付渠道参数信息放入redis缓存中

		try {
			upDateRedis(payChannelParamDTO.getAppId(),
			            payChannelParamDTO.getPlatformChannelCode(),
			            payChannelParamDTO.getPayChannel(), payChannelParamDTO);
		} catch (Exception e) {
			log.error(e.getMessage());
		}

		return payChannelParamDTO;
	}

	private void upDateRedis(String appId, String platformChannelCode, String payChannel,
	                         PayChannelParamDTO payChannelParamDTO) {
		String redisKey = RedisUtil.keyBuilder(appId, platformChannelCode, payChannel);

		System.out.println("redisKey================" + redisKey);

		cache.set(redisKey, JSON.toJSONString(payChannelParamDTO));
	}


	/**
	 * 获取指定应用指定服务类型下所包含的某个原始支付参数
	 *
	 * @param appId           appId
	 * @param platformChannel platformChannel
	 * @param payChannel      payChannel
	 * @return PayChannelParamDTO
	 */
	@Override
	public PayChannelParamDTO queryParamByAppPlatformAndPayChannel(String appId,
	                                                               String platformChannel,
	                                                               String payChannel) {
		// 先从缓存中查询
		try {
			// 根据所给数据生成redis的key值（所给值固定，key值也固定）
			String redisKey = RedisUtil.keyBuilder(appId, platformChannel, payChannel);
			// 根据key值得到value值,值为Json字符串
			String payChannelParamDtoString = cache.get(redisKey);
			if (!StringUtils.isEmpty(payChannelParamDtoString)) {
				// 把Json字符串转为相应对象
				return JSON.parseObject(payChannelParamDtoString,
				                        PayChannelParamDTO.class);
			}
		} catch (Exception e) {
			log.error(e.getMessage());
		}

		// 缓存中没有，从数据库中查询
		// 根据应用id和平台服务类型code获取应用绑定服务类型的id
		AppPlatformChannel appPlatformChannel =
				appPlatformChannelMapper
						.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
								           .eq(AppPlatformChannel::getAppId, appId)
								           .eq(AppPlatformChannel::getPlatformChannel, platformChannel));

		PayChannelParam payChannelParam = payChannelParamMapper.selectOne(new LambdaQueryWrapper<PayChannelParam>()
				                                                                  .eq(PayChannelParam::getAppPlatformChannelId,
				                                                                      appPlatformChannel.getId())
				                                                                  .eq(PayChannelParam::getPayChannel,
				                                                                      payChannel));


		// 查询完毕，将查询结果存入redis缓存
		PayChannelParamDTO payChannelParamDTO = PayChannelParamConvert.INSTANCE.entity2dto(payChannelParam);
		upDateRedis(appId, platformChannel, payChannel, payChannelParamDTO);

		return payChannelParamDTO;
	}

	/**
	 * 获取指定应用指定服务类型下所包含的原始支付渠道参数列表
	 *
	 * @param appId           应用id
	 * @param platformChannel 服务类型
	 * @return PayChannelParamDTOList
	 */
	@Override
	public List<PayChannelParamDTO> queryPayChannelParamByAppAndPlatform(String appId, String platformChannel) {
		//根据应用id和平台服务类型code获取应用绑定服务类型的id
		AppPlatformChannel appPlatformChannel =
				appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
						                                   .eq(AppPlatformChannel::getAppId, appId)
						                                   .eq(AppPlatformChannel::getPlatformChannel,
						                                       platformChannel));
		List<PayChannelParam> payChannelParams =
				payChannelParamMapper.selectList(new LambdaQueryWrapper<PayChannelParam>()
						                                 .eq(PayChannelParam::getAppPlatformChannelId,
						                                     appPlatformChannel.getId()));
		return PayChannelParamConvert.INSTANCE.listentity2listdto(payChannelParams);
	}


	/**
	 * 根据应用id和platformChannelCode查询platformChannel
	 *
	 * @param appId               应用id
	 * @param platformChannelCode platformChannelCode
	 * @return platformChannel
	 */
	public AppPlatformChannel findAppPlatformChannelByAppIdAndCode(String appId, String platformChannelCode) {

		return appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
				                                          .eq(AppPlatformChannel::getAppId, appId)
				                                          .eq(AppPlatformChannel::getPlatformChannel,
				                                              platformChannelCode));
	}
}
